home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / sound / namco.c < prev    next >
C/C++ Source or Header  |  2000-04-23  |  14KB  |  573 lines

  1. /***************************************************************************
  2.  
  3.     NAMCO sound driver.
  4.  
  5.     This driver handles the three known types of NAMCO wavetable sounds:
  6.  
  7.         - 3-voice mono (Pac-Man, Pengo, Dig Dug, etc)
  8.         - 8-voice mono (Mappy, Dig Dug 2, etc)
  9.         - 8-voice stereo (System 1)
  10.         - 6-voice stereo (Pole Position 1, Pole Position 2)
  11.  
  12. ***************************************************************************/
  13.  
  14. #include "driver.h"
  15.  
  16.  
  17. /* 8 voices max */
  18. #define MAX_VOICES 8
  19.  
  20.  
  21. /* this structure defines the parameters for a channel */
  22. typedef struct
  23. {
  24.     int frequency;
  25.     int counter;
  26.     int volume[2];
  27.     int noise_sw;
  28.     int noise_state;
  29.     int noise_seed;
  30.     int noise_counter;
  31.     const unsigned char *wave;
  32. } sound_channel;
  33.  
  34.  
  35. /* globals available to everyone */
  36. unsigned char *namco_soundregs;
  37. unsigned char *namco_wavedata;
  38.  
  39. /* data about the sound system */
  40. static sound_channel channel_list[MAX_VOICES];
  41. static sound_channel *last_channel;
  42.  
  43. /* global sound parameters */
  44. static const unsigned char *sound_prom;
  45. static int samples_per_byte;
  46. static int num_voices;
  47. static int sound_enable;
  48. static int stream;
  49. static int namco_clock;
  50. static int sample_rate;
  51.  
  52. /* mixer tables and internal buffers */
  53. static INT16 *mixer_table;
  54. static INT16 *mixer_lookup;
  55. static short *mixer_buffer;
  56. static short *mixer_buffer_2;
  57.  
  58.  
  59.  
  60. /* build a table to divide by the number of voices */
  61. static int make_mixer_table(int voices)
  62. {
  63.     int count = voices * 128;
  64.     int i;
  65.     int gain = 16;
  66.  
  67.  
  68.     /* allocate memory */
  69.     mixer_table = malloc(256 * voices * sizeof(INT16));
  70.     if (!mixer_table)
  71.         return 1;
  72.  
  73.     /* find the middle of the table */
  74.     mixer_lookup = mixer_table + (128 * voices);
  75.  
  76.     /* fill in the table - 16 bit case */
  77.     for (i = 0; i < count; i++)
  78.     {
  79.         int val = i * gain * 16 / voices;
  80.         if (val > 32767) val = 32767;
  81.         mixer_lookup[ i] = val;
  82.         mixer_lookup[-i] = -val;
  83.     }
  84.  
  85.     return 0;
  86. }
  87.  
  88.  
  89. /* generate sound to the mix buffer in mono */
  90. static void namco_update_mono(int ch, INT16 *buffer, int length)
  91. {
  92.     sound_channel *voice;
  93.     short *mix;
  94.     int i;
  95.  
  96.     /* if no sound, we're done */
  97.     if (sound_enable == 0)
  98.     {
  99.         memset(buffer, 0, length * sizeof(INT16));
  100.         return;
  101.     }
  102.  
  103.     /* zap the contents of the mixer buffer */
  104.     memset(mixer_buffer, 0, length * sizeof(short));
  105.  
  106.     /* loop over each voice and add its contribution */
  107.     for (voice = channel_list; voice < last_channel; voice++)
  108.     {
  109.         int f = voice->frequency;
  110.         int v = voice->volume[0];
  111.  
  112.         mix = mixer_buffer;
  113.  
  114.         if (voice->noise_sw)
  115.         {
  116.             /* only update if we have non-zero volume and frequency */
  117.             if (v && (f & 0xff))
  118.             {
  119.                 float fbase = (float)sample_rate / (float)namco_clock;
  120.                 int delta = (float)((f & 0xff) << 4) * fbase;
  121.                 int c = voice->noise_counter;
  122.  
  123.                 /* add our contribution */
  124.                 for (i = 0; i < length; i++)
  125.                 {
  126.                     int noise_data;
  127.                     int cnt;
  128.  
  129.                     if (voice->noise_state)    noise_data = 0x07;
  130.                     else noise_data = -0x07;
  131.                     *mix++ += noise_data * (v >> 1);
  132.  
  133.                     c += delta;
  134.                     cnt = (c >> 12);
  135.                     c &= (1 << 12) - 1;
  136.                     for( ;cnt > 0; cnt--)
  137.                     {
  138.                         if ((voice->noise_seed + 1) & 2) voice->noise_state ^= 1;
  139.                         if (voice->noise_seed & 1) voice->noise_seed ^= 0x28000;
  140.                         voice->noise_seed >>= 1;
  141.                     }
  142.                 }
  143.  
  144.                 /* update the counter for this voice */
  145.                 voice->noise_counter = c;
  146.             }
  147.         }
  148.         else
  149.         {
  150.             /* only update if we have non-zero volume and frequency */
  151.             if (v && f)
  152.             {
  153.                 const unsigned char *w = voice->wave;
  154.                 int c = voice->counter;
  155.  
  156.                 /* add our contribution */
  157.                 for (i = 0; i < length; i++)
  158.                 {
  159.                     int offs;
  160.  
  161.                     c += f;
  162.                     offs = (c >> 15) & 0x1f;
  163.                     if (samples_per_byte == 1)    /* use only low 4 bits */
  164.                         *mix++ += ((w[offs] & 0x0f) - 8) * v;
  165.                     else    /* use full byte, first the high 4 bits, then the low 4 bits */
  166.                     {
  167.                         if (offs & 1)
  168.                             *mix++ += ((w[offs>>1] & 0x0f) - 8) * v;
  169.                         else
  170.                             *mix++ += (((w[offs>>1]>>4) & 0x0f) - 8) * v;
  171.                     }
  172.                 }
  173.  
  174.                 /* update the counter for this voice */
  175.                 voice->counter = c;
  176.             }
  177.         }
  178.     }
  179.  
  180.     /* mix it down */
  181.     mix = mixer_buffer;
  182.     for (i = 0; i < length; i++)
  183.         *buffer++ = mixer_lookup[*mix++];
  184. }
  185.  
  186.  
  187. /* generate sound to the mix buffer in stereo */
  188. static void namco_update_stereo(int ch, INT16 **buffer, int length)
  189. {
  190.     sound_channel *voice;
  191.     short *lmix, *rmix;
  192.     int i;
  193.  
  194.     /* if no sound, we're done */
  195.     if (sound_enable == 0)
  196.     {
  197.         memset(buffer[0], 0, length * sizeof(INT16));
  198.         memset(buffer[1], 0, length * sizeof(INT16));
  199.         return;
  200.     }
  201.  
  202.     /* zap the contents of the mixer buffer */
  203.     memset(mixer_buffer, 0, length * sizeof(INT16));
  204.     memset(mixer_buffer_2, 0, length * sizeof(INT16));
  205.  
  206.     /* loop over each voice and add its contribution */
  207.     for (voice = channel_list; voice < last_channel; voice++)
  208.     {
  209.         int f = voice->frequency;
  210.         int lv = voice->volume[0];
  211.         int rv = voice->volume[1];
  212.  
  213.         lmix = mixer_buffer;
  214.         rmix = mixer_buffer_2;
  215.  
  216.         if (voice->noise_sw)
  217.         {
  218.             /* only update if we have non-zero volume and frequency */
  219.             if ((lv || rv) && (f & 0xff))
  220.             {
  221.                 float fbase = (float)sample_rate / (float)namco_clock;
  222.                 int delta = (float)((f & 0xff) << 4) * fbase;
  223.                 int c = voice->noise_counter;
  224.  
  225.                 /* add our contribution */
  226.                 for (i = 0; i < length; i++)
  227.                 {
  228.                     int noise_data;
  229.                     int cnt;
  230.  
  231.                     if (voice->noise_state)    noise_data = 0x07;
  232.                     else noise_data = -0x07;
  233.                     *lmix++ += noise_data * (lv >> 1);
  234.                     *rmix++ += noise_data * (rv >> 1);
  235.  
  236.                     c += delta;
  237.                     cnt = (c >> 12);
  238.                     c &= (1 << 12) - 1;
  239.                     for( ;cnt > 0; cnt--)
  240.                     {
  241.                         if ((voice->noise_seed + 1) & 2) voice->noise_state ^= 1;
  242.                         if (voice->noise_seed & 1) voice->noise_seed ^= 0x28000;
  243.                         voice->noise_seed >>= 1;
  244.                     }
  245.                 }
  246.  
  247.                 /* update the counter for this voice */
  248.                 voice->noise_counter = c;
  249.             }
  250.         }
  251.         else
  252.         {
  253.             /* only update if we have non-zero volume and frequency */
  254.             if ((lv || rv) && f)
  255.             {
  256.                 const unsigned char *w = voice->wave;
  257.                 int c = voice->counter;
  258.  
  259.                 /* add our contribution */
  260.                 for (i = 0; i < length; i++)
  261.                 {
  262.                     int offs;
  263.  
  264.                     c += f;
  265.                     offs = (c >> 15) & 0x1f;
  266.                     if (samples_per_byte == 1)    /* use only low 4 bits */
  267.                     {
  268.                         *lmix++ += ((w[offs] & 0x0f) - 8) * lv;
  269.                         *rmix++ += ((w[offs] & 0x0f) - 8) * rv;
  270.                     }
  271.                     else    /* use full byte, first the high 4 bits, then the low 4 bits */
  272.                     {
  273.                         if (offs & 1)
  274.                         {
  275.                             *lmix++ += ((w[offs>>1] & 0x0f) - 8) * lv;
  276.                             *rmix++ += ((w[offs>>1] & 0x0f) - 8) * rv;
  277.                         }
  278.                         else
  279.                         {
  280.                             *lmix++ += (((w[offs>>1]>>4) & 0x0f) - 8) * lv;
  281.                             *rmix++ += (((w[offs>>1]>>4) & 0x0f) - 8) * rv;
  282.                         }
  283.                     }
  284.                 }
  285.  
  286.                 /* update the counter for this voice */
  287.                 voice->counter = c;
  288.             }
  289.         }
  290.     }
  291.  
  292.     /* mix it down */
  293.     lmix = mixer_buffer;
  294.     rmix = mixer_buffer_2;
  295.     {
  296.         INT16 *dest1 = buffer[0];
  297.         INT16 *dest2 = buffer[1];
  298.         for (i = 0; i < length; i++)
  299.         {
  300.             *dest1++ = mixer_lookup[*lmix++];
  301.             *dest2++ = mixer_lookup[*rmix++];
  302.         }
  303.     }
  304. }
  305.  
  306.  
  307. int namco_sh_start(const struct MachineSound *msound)
  308. {
  309.     const char *mono_name = "NAMCO sound";
  310.     const char *stereo_names[] =
  311.     {
  312.         "NAMCO sound left",
  313.         "NAMCO sound right"
  314.     };
  315.     sound_channel *voice;
  316.     const struct namco_interface *intf = msound->sound_interface;
  317.  
  318.     namco_clock = intf->samplerate;
  319.     sample_rate = Machine->sample_rate;
  320.  
  321.     /* get stream channels */
  322.     if (intf->stereo)
  323.     {
  324.         int vol[2];
  325.  
  326.         vol[0] = MIXER(intf->volume,MIXER_PAN_LEFT);
  327.         vol[1] = MIXER(intf->volume,MIXER_PAN_RIGHT);
  328.         stream = stream_init_multi(2, stereo_names, vol, intf->samplerate, 0, namco_update_stereo);
  329.     }
  330.     else
  331.     {
  332.         stream = stream_init(mono_name, intf->volume, intf->samplerate, 0, namco_update_mono);
  333.     }
  334.  
  335.     /* allocate a pair of buffers to mix into - 1 second's worth should be more than enough */
  336.     if ((mixer_buffer = malloc(2 * sizeof(short) * intf->samplerate)) == 0)
  337.         return 1;
  338.     mixer_buffer_2 = mixer_buffer + intf->samplerate;
  339.  
  340.     /* build the mixer table */
  341.     if (make_mixer_table(intf->voices))
  342.     {
  343.         free (mixer_buffer);
  344.         return 1;
  345.     }
  346.  
  347.     /* extract globals from the interface */
  348.     num_voices = intf->voices;
  349.     last_channel = channel_list + num_voices;
  350.  
  351.     if (intf->region == -1)
  352.     {
  353.         sound_prom = namco_wavedata;
  354.         samples_per_byte = 2;    /* first 4 high bits, then low 4 bits */
  355.     }
  356.     else
  357.     {
  358.         sound_prom = memory_region(intf->region);
  359.         samples_per_byte = 1;    /* use only low 4 bits */
  360.     }
  361.  
  362.     /* start with sound enabled, many games don't have a sound enable register */
  363.     sound_enable = 1;
  364.  
  365.     /* reset all the voices */
  366.     for (voice = channel_list; voice < last_channel; voice++)
  367.     {
  368.         voice->frequency = 0;
  369.         voice->volume[0] = voice->volume[1] = 0;
  370.         voice->wave = &sound_prom[0];
  371.         voice->counter = 0;
  372.         voice->noise_sw = 0;
  373.         voice->noise_state = 0;
  374.         voice->noise_seed = 1;
  375.         voice->noise_counter = 0;
  376.     }
  377.  
  378.     return 0;
  379. }
  380.  
  381.  
  382. void namco_sh_stop(void)
  383. {
  384.     free (mixer_table);
  385.     free (mixer_buffer);
  386. }
  387.  
  388.  
  389. /********************************************************************************/
  390.  
  391.  
  392. WRITE_HANDLER( pengo_sound_enable_w )
  393. {
  394.     sound_enable = data;
  395. }
  396.  
  397. WRITE_HANDLER( pengo_sound_w )
  398. {
  399.     sound_channel *voice;
  400.     int base;
  401.  
  402.     /* update the streams */
  403.     stream_update(stream, 0);
  404.  
  405.     /* set the register */
  406.     namco_soundregs[offset] = data & 0x0f;
  407.  
  408.     /* recompute all the voice parameters */
  409.     for (base = 0, voice = channel_list; voice < last_channel; voice++, base += 5)
  410.     {
  411.         voice->frequency = namco_soundregs[0x14 + base];    /* always 0 */
  412.         voice->frequency = voice->frequency * 16 + namco_soundregs[0x13 + base];
  413.         voice->frequency = voice->frequency * 16 + namco_soundregs[0x12 + base];
  414.         voice->frequency = voice->frequency * 16 + namco_soundregs[0x11 + base];
  415.         if (base == 0)    /* the first voice has extra frequency bits */
  416.             voice->frequency = voice->frequency * 16 + namco_soundregs[0x10 + base];
  417.         else
  418.             voice->frequency = voice->frequency * 16;
  419.  
  420.         voice->volume[0] = namco_soundregs[0x15 + base] & 0x0f;
  421.         voice->wave = &sound_prom[32 * (namco_soundregs[0x05 + base] & 7)];
  422.     }
  423. }
  424.  
  425.  
  426. /********************************************************************************/
  427.  
  428. WRITE_HANDLER( polepos_sound_w )
  429. {
  430.     sound_channel *voice;
  431.     int base;
  432.  
  433.     /* update the streams */
  434.     stream_update(stream, 0);
  435.  
  436.     /* set the register */
  437.     namco_soundregs[offset] = data;
  438.  
  439.     /* recompute all the voice parameters */
  440.     for (base = 8, voice = channel_list; voice < last_channel; voice++, base += 4)
  441.     {
  442.         voice->frequency = namco_soundregs[0x01 + base];
  443.         voice->frequency = voice->frequency * 256 + namco_soundregs[0x00 + base];
  444.  
  445.         /* the volume seems to vary between one of these five places */
  446.         /* it's likely that only 3 or 4 are valid; for now, we just */
  447.         /* take the maximum volume and that seems to do the trick */
  448.         /* volume[0] = left speaker ?, volume[1] = right speaker ? */
  449.         voice->volume[0] = voice->volume[1] = 0;
  450.         // front speaker ?
  451.         voice->volume[1] |= namco_soundregs[0x02 + base] & 0x0f;
  452.         voice->volume[0] |= namco_soundregs[0x02 + base] >> 4;
  453.         // rear speaker ?
  454.         voice->volume[1] |= namco_soundregs[0x03 + base] & 0x0f;
  455.         voice->volume[0] |= namco_soundregs[0x03 + base] >> 4;
  456.         voice->volume[1] |= namco_soundregs[0x23 + base] >> 4;
  457.         voice->wave = &sound_prom[32 * (namco_soundregs[0x23 + base] & 7)];
  458.     }
  459. }
  460.  
  461.  
  462. /********************************************************************************/
  463.  
  464. WRITE_HANDLER( mappy_sound_enable_w )
  465. {
  466.     sound_enable = offset;
  467. }
  468.  
  469. WRITE_HANDLER( mappy_sound_w )
  470. {
  471.     sound_channel *voice;
  472.     int base;
  473.  
  474.     /* update the streams */
  475.     stream_update(stream, 0);
  476.  
  477.     /* set the register */
  478.     namco_soundregs[offset] = data;
  479.  
  480.     /* recompute all the voice parameters */
  481.     for (base = 0, voice = channel_list; voice < last_channel; voice++, base += 8)
  482.     {
  483.         voice->frequency = namco_soundregs[0x06 + base] & 15;    /* high bits are from here */
  484.         voice->frequency = voice->frequency * 256 + namco_soundregs[0x05 + base];
  485.         voice->frequency = voice->frequency * 256 + namco_soundregs[0x04 + base];
  486.  
  487.         voice->volume[0] = namco_soundregs[0x03 + base] & 0x0f;
  488.         voice->wave = &sound_prom[32 * ((namco_soundregs[0x06 + base] >> 4) & 7)];
  489.     }
  490. }
  491.  
  492.  
  493. /********************************************************************************/
  494.  
  495. WRITE_HANDLER( namcos1_sound_w )
  496. {
  497.     sound_channel *voice;
  498.     int base;
  499.     static int nssw;
  500.  
  501.     /* verify the offset */
  502.     if (offset > 63)
  503.     {
  504.         logerror("NAMCOS1 sound: Attempting to write past the 64 registers segment\n");
  505.         return;
  506.     }
  507.  
  508.     /* update the streams */
  509.     stream_update(stream,0);
  510.  
  511.     /* set the register */
  512.     namco_soundregs[offset] = data;
  513.  
  514.     /* recompute all the voice parameters */
  515.     for (base = 0, voice = channel_list; voice < last_channel; voice++, base += 8)
  516.     {
  517.         voice->frequency = namco_soundregs[0x01 + base] & 15;    /* high bits are from here */
  518.         voice->frequency = voice->frequency * 256 + namco_soundregs[0x02 + base];
  519.         voice->frequency = voice->frequency * 256 + namco_soundregs[0x03 + base];
  520.  
  521.         voice->volume[0] = namco_soundregs[0x00 + base] & 0x0f;
  522.         voice->volume[1] = namco_soundregs[0x04 + base] & 0x0f;
  523.         voice->wave = &sound_prom[32/samples_per_byte * ((namco_soundregs[0x01 + base] >> 4) & 15)];
  524.  
  525.         nssw = ((namco_soundregs[0x04 + base] & 0x80) >> 7);
  526.         if ((voice + 1) < last_channel) (voice + 1)->noise_sw = nssw;
  527.     }
  528.     voice = channel_list;
  529.     voice->noise_sw = nssw;
  530. }
  531.  
  532. READ_HANDLER( namcos1_sound_r )
  533. {
  534.     return namco_soundregs[offset];
  535. }
  536.  
  537. WRITE_HANDLER( namcos1_wavedata_w )
  538. {
  539.     /* update the streams */
  540.     stream_update(stream,0);
  541.  
  542.     namco_wavedata[offset] = data;
  543. }
  544.  
  545. READ_HANDLER( namcos1_wavedata_r )
  546. {
  547.     return namco_wavedata[offset];
  548. }
  549.  
  550.  
  551. /********************************************************************************/
  552.  
  553. WRITE_HANDLER( snkwave_w )
  554. {
  555.     static int freq0 = 0xff;
  556.     sound_channel *voice = channel_list;
  557.     if( offset==0 ) freq0 = data;
  558.     if( offset==1 )
  559.     {
  560.         stream_update(stream, 0);
  561.         if( data==0xff || freq0==0 )
  562.         {
  563.             voice->volume[0] = 0x0;
  564.         }
  565.         else
  566.         {
  567.             voice->volume[0] = 0x8;
  568.             voice->frequency = (data<<16)/freq0;
  569.         }
  570.     }
  571. }
  572.  
  573.